Docker

1.Docker简介

        容器虚拟化,比传统的虚拟化轻量

        2013年出现,发展非常迅猛

        Redhat在6.5版本开始支持docker

        使用go语言开发,基于apache2.0协议

        开源软件,项目代码在github维护

容器虚拟化和传统虚拟化比较

01

02

Docker的优势

        启动非常快,秒级实现

        资源利用率很高,一台机器可以跑上千个docker容器

        更快的交付和部署,一次创建和配置后,可以在任意地方运行

        内核级别的虚拟化,不需要额外的hypevisor支持,会有更高的性能和效率

        易迁移,平台依赖性不强

03

Docker核心概念

        镜像,是一个只读的模板,类似于安装系统用到的那个iso文件,我们通过镜像来完成各种应用的部署。

        容器,镜像类似于操作系统,而容器类似于虚拟机本身。它可以被启动、开始、停止、删除等操作,每个容器都是相互隔离的。

        仓库,存放镜像的一个场所,仓库分为公开仓库和私有仓库。 最大的公开仓库是Docker hub(hub.docker.com),国内公开仓库(dockerpool.com)

2.Docker安装

centos6 上安装

1
2
[root@docker ~]# yum install -y epel-release
[root@docker ~]# yum install -y docker-io

        启动docker

1
[root@docker ~]# /etc/init.d/docker start

        如status 查看状态

04

        解决办法如下

1
[root@docker ~]# yum install device-mapper-event-libs

        重启 docker 正常运行

1
2
3
4
5
[root@docker ~]# service docker restart
停止 docker: [失败]
Starting docker: [确定]
[root@docker ~]# service docker status
docker (pid 24216) 正在运行...

centos7 上安装

1
[root@docker ~]# yum install -y docker

        启动docker

1
[root@docker ~]# systemctl start docker

3.Docker 镜像管理

        从docker.com获取centos镜像 docker pull centos

1
2
3
4
5
6
7
[root@docker ~]# docker pull centos
Using default tag: latest
Trying to pull repository docker.io/library/centos ...
latest: Pulling from docker.io/library/centos
45a2e645736c: Pull complete
Digest: sha256:c577af3197aacedf79c5a204cd7f493c8e07ffbce7f88f7600bf19c688c38799
Status: Downloaded newer image for docker.io/centos:latest

        docker images 查看本地都有哪些镜像

1
2
3
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 67591570dd29 5 weeks ago 191.8 MB

        docker tag centos yanyi 为centos镜像设置标签为yanyi

1
[root@docker ~]# docker tag centos yanyi

        再使用docker images查看会多出来一行,改行的image id和centos的一样

1
2
3
4
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 67591570dd29 5 weeks ago 191.8 MB
yanyi latest 67591570dd29 5 weeks ago 191.8 MB

        docker search [image-name] 从docker仓库搜索docker镜像,后面是关键词

1
[root@docker ~]# docker search centos

        docker run -t -i centos /bin/bash 用下载到的镜像开启容器,-i表示让容器的标准输入打开,-t表示分配一个伪终端,要把-i -t 放到镜像名字前面

1
[root@docker ~]# docker run -t -i centos /bin/bash

        当该镜像发生修改后,我们可以把该镜像提交重新生成一个新版本进行在本地。

05

        docker ps 查看运行的容器,加上-a选项可以查看没有运行的容器

1
[root@docker ~]# docker ps
1
2
3
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e35c7590c0e centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago desperate_jepsen

        docker rmi centos 用来删除指定镜像, 其中后面的参数可以是tag,如果是tag时,实际上是删除该tag,只要该镜像还有其他tag,就不会删除该镜像。当后面的参数为镜像ID时,则会彻底删除整个镜像,连通所有标签一同删除

1
2
3
[root@docker ~]# docker rmi yanyi
Untagged: yanyi:latest
Untagged: docker.io/centos@sha256:c577af3197aacedf79c5a204cd7f493c8e07ffbce7f88f7600bf19c688c38799

        tag 是可以更改的

1
2
3
4
5
6
7
8
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 67591570dd29 5 weeks ago 191.8 MB
[root@docker ~]# docker tag centos centos:yanyi
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos yanyi 67591570dd29 5 weeks ago 191.8 MB
docker.io/centos latest 67591570dd29 5 weeks ago 191.8 MB

4.docker 镜像使用容器生成新的镜像

        docker ps 可以查看运行的镜像

1
2
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

        说明现在没有运行的镜像,用 docker ps -a 查看没有运行的镜像

1
2
3
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e35c7590c0e centos "/bin/bash" 36 hours ago Exited (0) 36 hours ago desperate_jepsen

        运行没有运行的镜像,命令 docker start CONTAINER ID可以只输入前3位

1
2
3
4
5
[root@docker ~]# docker start 6e3
6e3
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e35c7590c0e entos "/bin/bash" 36 hours ago Up 9 seconds desperate_jepsen

        进入运行镜像,命令 docker exec -it /bin/bash 也可以只输入前3位

1
2
[root@docker ~]# docker exec -i -t 6e3 /bin/bash
[root@6e35c7590c0e /]#

        在镜像中可以执行一些命令

1
[root@914ff4a5efee /]# yum install -y net-tools wget

        也可以查看镜像版本

1
2
[root@914ff4a5efee /]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
1
2
[root@914ff4a5efee /]# uname -a
Linux 914ff4a5efee 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Docker 基于已有镜像的容器创建镜像

        运行docker run后,进入到该容器中,我们做一些变更,比如安装一些东西,然后针对这个容器进行创建新的镜像

        docker commit -m “change somth” -a “somebody info” container_id (通过docker ps -a获取id) 新镜像名字

        例如:

1
2
3
4
5
6
7
[root@docker ~]# docker commit -m "centos_with_nettools_and_wget" -a "yanyi" 914 centos_with_net
sha256:230c1f5d9646084a345b40f75d5eca5d62f4bf7cde8ba03d26a5b161057da55b
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_with_net latest 230c1f5d9646 14 seconds ago 262.7 MB
centos latest 67591570dd29 5 weeks ago 191.8 MB
centos yanyi 67591570dd29 5 weeks ago 191.8 MB

        这个命令有点像svn的提交,-m 加一些改动信息,-a 指定作者相关信息 914这一串为容器id,再后面为新镜像的名字

5.Docker 基于本地模板导入创建镜像

        模块获取,可以直接在网上下载一个模块https://openvz.org/Download/template/precreated 可惜速度并不快,若下载了一个centos的模板 centos-6-x86_64-minimal.tar.gz 那么导入该镜像的命令为:

1
2
[root@docker ~]# cat centos-6-x86_64-minimal.tar.gz |docker import - centos-6-x86_64
sha256:601270b7e8af4f738fc5d22c0c6b9aa653ebfa917e9a5dcc371a894ed17cb7a1

        把现有镜像,导出为一个文件:

1
[root@docker ~]# docker save -o centos_with_net.tar 230c1f5d9646

        还可以用该文件恢复本地镜像:

1
[root@docker ~]# docker load --input centos_with_net.tar

        或者

1
[root@docker ~]# docker load < centos_with_net.tar

        docker push image_name 可以把自己的镜像传到dockerhub官方网站上去,但前提是需要先注册一个用户

6.Docker 容器管理

        docker create -it centos 这样可以创建一个容器,但该容器并没有启动

1
2
[root@docker ~]# docker create -i -t centos
15cb91256d663c18dea652145b5e970220d0295879bbd8647db276eff36a1a76

        docker start container_id 启动容器后,可以使用 docker ps 查看到,有start 就有stop,和restart

1
2
[root@docker ~]# docker start 15cb91256d66
15cb91256d66

        之前我们使用的docker run 相当于先create再start

        docker attach 可以进入一个后台运行的容器,比如 docker attach container_id

1
2
[root@docker ~]# docker attach 15cb91256d66
[root@15cb91256d66 /]#

        但是attach命令不算好用,比如我们想要退出终端,就得exit了,这样容器也就退出了,还有一种方法docker exec -i -t container_id /bin/bash #可以临时打开一个虚拟终端,并且exit后,容器依然运行着

1
2
[root@docker ~]# docker exec -i -t 15cb91256d66 /bin/bash
[root@15cb91256d66 /]#
1
2
[root@docker ~]# docker run -i -t centos-6-x86_64 /bin/bash
[root@2983f5289991 /]#

        这样进入了一个虚拟终端里面,我们可以运行一些命令,使用命令exit或者ctrl d 退出该bash,当退出后这个容器也会停止。

        docker run -d 可以让容器在后台运行

        比如:

1
2
[root@docker ~]# docker run -d centos_with_net bash -c "while :; do echo 123; sleep 1; done "
9afe4cdb5e63604a12045b104fa26008c84267665f27bf2bedebe5e6432b814f

        停止镜像 docker stop container_id

1
2
[root@docker ~]# docker stop 9afe
9afe

        docker run –name web -itd centos bash –name 给容器自定义名字

1
[root@docker ~]# docker run -i -t -d --name web centos bash

        docker logs 可以获取到容器的运行历史信息,用法如下docker logs container_id

1
[root@docker ~]# docker logs 9afe

        docker rm container_id #container_id是ps的时候查看到的,这样就可以把所有container删除。如果是运行的容器,可以加-f

1
2
[root@docker ~]# docker rm 9afe4cdb5e63
9afe4cdb5e63

        如果是运行的容器,可以加-f

1
2
3
4
5
6
7
8
9
10
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e35c7590c0e centos "/bin/bash" 2 days ago Up 4 seconds desperate_jepsen
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e35c7590c0e centos "/bin/bash" 2 days ago Up 7 seconds desperate_jepsen
[root@docker ~]# docker rm -f 6e35c7590c0e
6e35c7590c0e
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

        docker run –rm -it centos bash -c “sleep 30” #–rm 可以让容器退出后直接删除,在这里命令执行完容器就会退出,不能和-d一起使用

        docker export container_id > file.tar 导出容器

1
2
3
4
5
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c42f598d215e centos "bash" 16 hours ago Up 9 seconds web
914ff4a5efee centos "/bin/bash" 27 hours ago Up 15 seconds high_mccarthy
[root@docker ~]# docker export c42f > yanyi_centos.tar

        可以迁移到其他机器上,需要导入cat file.tar |docker import - yanyi_centos#这样会生成yanyi_centos的镜像

1
2
3
4
5
[root@docker ~]# cat yanyi_centos.tar | docker import - yanyi_centos
sha256:7092ed59698a2c1fbff09f883bb525d6d5fea78bbf96885ad5780459ca5bd06d
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
yanyi_centos latest 7092ed59698a About a minute ago 191.8 MB

7.Docker 仓库管理

下载 registry 镜像

        docker pull registry #下载registry 镜像,registy为docker官方提供的一个镜像,我们可以用它来创建本地的docker私有仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@docker ~]# docker pull registry:0.6.7
Trying to pull repository docker.io/library/registry ...
0.6.7: Pulling from docker.io/library/registry
a3ed95caeb02: Pull complete
b744ac11e87c: Pull complete
df38afb9684e: Pull complete
0018b940d299: Pull complete
0f24c060f901: Pull complete
95ce9ef4df17: Pull complete
89843edaf725: Pull complete
d1350903a0ac: Pull complete
a8f3ba806716: Pull complete
edeb8014d2ad: Pull complete
d0b78626245e: Pull complete
Digest: sha256:b48ecc989fd0b79a16c2bfe59df5354e3fe85b562ef9f7361eac4bcd19585f5d
Status: Downloaded newer image for docker.io/registry:0.6.7

启动容器

        docker run -d -p 5000:5000 registy #以registry镜像启动容器,监听5000端口

1
2
[root@docker ~]# docker run -d -p 5000:5000 registry
00361bd4d3390430d61db003b7375208e82902e4bb855e5cebfb210da743121f

        curl 127.0.0.1:5000 #可以访问它

1
2
[root@docker ~]# curl 127.0.0.1:5000
"docker-registry server (dev)"

        也可以

1
2
3
4
5
[root@docker ~]# telnet 127.0.0.1 5000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.

        下面我们来把其中一个镜像上传到私有仓库

        docker tag docker.io/busybox 192.168.0.96:5000/busybox #标记一下tag,必须要带有私有仓库的ip:port

1
[root@docker ~]# docker tag docker.io/busybox 192.168.0.96:5000/busybox

        docker push 192.168.0.96:5000/busybox

1
[root@docker ~]# docker push 192.168.0.96:5000/busybox

        此时报错了类似如下

  • cnetos 6
1
2
3
Error response from daemon: invalid registry endpoint https://192.168.0.96:5000/v0/: unable to ping registry endpoint https://192.168.0.96:5000/v0/
v2 ping attempt failed with error: Get https://192.168.0.96:5000/v2/: EOF
v1 ping attempt failed with error: Get https://192.168.0.96:5000/v1/_ping: EOF. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry 192.168.0.96:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/192.168.0.96:5000/ca.crt
  • centos 7
1
2
3
4
The push refers to a repository [192.168.0.96:5000/busybox]
unable to ping registry endpoint https://192.168.0.96:5000/v0/
v2 ping attempt failed with error: Get https://192.168.0.96:5000/v2/: EOF
v1 ping attempt failed with error: Get https://192.168.0.96:5000/v1/_ping: EOF

        这是因为Docker从1.3.X之后,与docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报上面的错误。为了解决这个问题需要在启动docker server时增加启动参数为默认使用http访问。解决该问题的方法为:

  • centos 6
1
[root@docker ~]# vim /etc/init.d/docker

        把 $exec -d $other_args 改为
$exec -d –insecure-registry 192.168.0.96:5000 $other_args

06

        改为

07

        然后重启docker

1
[root@docker ~]# service docker restart
  • centos 7
1
[root@docker ~]# vim /etc/sysconfig/docker

        加上 ADD_REGISTRY=’–add-registry 192.168.0.96:5000’ 和 INSECURE_REGISTRY=’–insecure-registry 192.168.0.96:5000’

08

09

        然后重启docker

1
[root@docker ~]# systemctl restart docker

        再启动registry容器 docker start registry_container_id

1
[root@docker ~]# docker start 00361bd4d339

        再次把镜像上传私有仓库

1
2
3
4
[root@docker ~]# docker push 192.168.0.96:5000/busybox
The push refers to a repository [192.168.0.96:5000/busybox]
38ac8d0f5bb3: Pushed
latest: digest: sha256:2efce9f5b0cb8815d192ae634b4c87943d0f0b873d98487ee98f8ed0504bd572 size: 527

        查看私有仓库里面的所有镜像命令(版本不同命令不一样)

        curl http://192.168.0.96:5000/v1/search

        curl http://192.168.0.96:5000/v2/_catalog #最近版本(33.28m)

1
2
[root@docker ~]# curl http://192.168.0.96:5000/v2/_catalog
{"repositories":["busybox"]}

        curl http://192.168.0.96:5000/v2/image_name/tags/list #最近版本(33.28m)

1
2
[root@docker ~]# curl http://192.168.0.96:5000/v2/busybox/tags/list
{"name":"busybox","tags":["latest"]}

        docker search 192.168.0.96:5000

8.Docker 数据管理

挂载本地的目录到容器里

        docker run -tid -v /data/:/data centos bash #-v 用来指定挂载目录,:前面的/data/为本地目录,:后面的/data/为容器里的目录

1
2
3
[root@docker ~]# mkdir /data/
[root@docker ~]# docker run -itd -v /data/:/data1 centos bash
cdb5c8a578d5f720df7a263a41d84c22118696f9e5dae7591f539fb4f83ecb16

        测试,本地 data 目录下创建文件在容器内查看。

1
2
3
4
5
6
7
8
9
[root@docker ~]# touch /data/1.txt
[root@docker ~]# echo asdjfklasdjfklasdjf > /data/1.txt
[root@docker ~]# cat /data/1.txt
asdjfklasdjfklasdjf
[root@docker ~]# docker exec -it cdb5 bash
[root@cdb5c8a578d5 /]# ls /data1/
1.txt
[root@cdb5c8a578d5 /]# cat /data1/1.txt
asdjfklasdjfklasdjf

        容器创建文件,在本地目录查看

1
2
3
4
[root@cdb5c8a578d5 /]# touch /data1/2.txt
[root@cdb5c8a578d5 /]# exit
[root@docker ~]# ls /data/
1.txt 2.txt

挂载数据卷

        其实我们挂载目录的时候,可以指定容器name,如果不指定就随机定义了。比如上面我们没有指定,它就生成了一个名字为angry_bell,这个名字可以使用命令 docker ps 看最右侧一列 docker run -itd –volumes-from angry_bell centos bash

1
2
[root@docker ~]# docker run -itd --volumes-from angry_bell centos bash
e36d478d9253a4758b28fb3a3bc5596781b4e572797aee2623bfcf5f50d6492d

        这样,我们使用 centos 镜像创建了新的容器,并且使用了 angry_bell 容器的数据卷。我们可以在新容器的数据卷下创建文件,然后去 angry_bell 容器里查看。

1
2
3
4
5
6
7
8
[root@docker ~]# docker exec -it e36 bash
[root@e36d478d9253 /]# ls /data1
1.txt 2.txt
[root@e36d478d9253 /]# touch /data1/3.txt
[root@e36d478d9253 /]# exit
[root@docker ~]# docker exec -it cdb bash
[root@cdb5c8a578d5 /]# ls /data1/
1.txt 2.txt 3.txt

定义数据卷容器

        有时候,我们需要多个容器之间相互共享数据,类似于linux里面的NFS,所以就可以搭建一个专门的数据卷容器,然后其他容器直接挂载该数据卷。

        首先建立数据卷容器

        docker run -itd -v /data/ –name centos_testvol centos bash #注意这里的/data/是容器的/data目录,并非本地的/data/目录。

1
2
[root@docker ~]# docker run -itd -v /data/ --name centos_testvol centos bash
cfe772a30a89886d9603e84f3078052a39f6119d8b9561752d5d2eb83b245835

        然后让其他容器挂载该数据卷 docker run -itd –volumes-from centos_testvol centos bash

1
2
[root@docker ~]# docker run -itd --volumes-from centos_testvol centos bash
d3cd4e6611e18226ceb4f4622bd55c534fb313865566cc7819556b3a1a53e530

        查看是否成功

1
2
3
4
5
6
7
8
9
10
[root@docker ~]# docker exec -it d3c bash
[root@d3cd4e6611e1 /]# ls /data
[root@d3cd4e6611e1 /]# mkdir /data/test
[root@d3cd4e6611e1 /]# touch /data/test/1.txt
[root@d3cd4e6611e1 /]# exit
[root@docker ~]# docker exec -it centos_testvol bash
[root@cfe772a30a89 /]# ls /data
test
[root@cfe772a30a89 /]# ls /data/test
1.txt

Docker 数据管理 - 数据卷的备份与恢复

备份

1
2
3
4
5
6
7
8
9
10
11
[root@docker ~]# mkdir /vol_data_backup
[root@docker ~]# docker run -itd --volumes-from centos_testvol -v /vol_data_backup/:/backup centos bash
b246db616639574e1d6fe5ceb3534337df71676af3362d1b4dfd3b627523be30
[root@docker ~]# docker exec -it b246 bash
[root@b246db616639 /]# tar cvf /backup/data.tar /data/
tar: Removing leading `/' from member names
/data/
/data/test/
/data/test/1.txt
[root@b246db616639 /]# ls /backup
data.tar

        也可以直接执行命令:docker run –volumes-from centos_testvol -v /vol_data_backup/:/backup centos tar cvf /backup/data.tar /data/

1
[root@docker ~]# docker run --volumes-from centos_testvol -v /vol_data_backup/:/backup centos tar cvf /backup/data.tar /data/

        说明:首先我们需要使用testvol数据卷新开一个容器,同时我们还需要把本地的/vol_data_backup/目录挂载到该容器的/backup下,这样在容器中/backup目录里面新建的文件,我们就可以直接在/vol_data_backup/目录中看到了。 然后再把/data/目录下面的文件打包到成data.tar文件放到/backup目录下面。

恢复

        思路: 先新建一个数据卷容器,再建一个新的容器并挂载该数据卷容器,然后再把tar包解包。

        新建数据卷容器:docker run -itd -v /data/ –name centos_testvol2 centos bash

1
2
[root@docker ~]# docker run -itd -v /data/ --name centos_testvol2 centos bash
00e733d06ece150b114490a36f0a751bed4f43de9aaede13e74331fcdeb87518

        挂载数据卷新建容器,并解包:

1
2
3
4
5
6
7
[root@docker ~]# docker run -itd --volumes-from centos_testvol2 -v /vol_data_backup/:/backup centos bash
3f9a5887e0dac36b9bd29c5e0925a27d627b39f1945bed66d471e8bccc0cde70
[root@docker ~]# docker exec -it 3f9a bash
[root@3f9a5887e0da /]# tar xvf /backup/data.tar
data/
data/test/
data/test/1.txt

        也可以执行命令:docker run –volumes-from centos_testvol2 -v /vol_data_backup/:/backup centos tar xvf /backup/data.tar

1
[root@docker ~]# docker run --volumes-from centos_testvol2 -v /vol_data_backup/:/backup centos tar xvf /backup/data.tar

9.Docker 网络管理 - 四种网络模式

host模式

        host模式,使用docker run时使用–net=host指定

        docker使用的网络实际上和宿主机一样,在容器内看到的网卡ip是宿主机上的ip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@docker ~]# docker run -it --rm --net=host centos_with_net bash
[root@docker /]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:69ff:fe81:dca8 prefixlen 64 scopeid 0x20<link>
ether 02:42:69:81:dc:a8 txqueuelen 0 (Ethernet)
RX packets 1551 bytes 79846 (77.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1642 bytes 8892494 (8.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.96 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::b5f:e696:2650:f930 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:5a:19:a5 txqueuelen 1000 (Ethernet)
RX packets 14059 bytes 9848234 (9.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5604 bytes 576835 (563.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@docker /]# exit
[root@docker ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:69ff:fe81:dca8 prefixlen 64 scopeid 0x20<link>
ether 02:42:69:81:dc:a8 txqueuelen 0 (Ethernet)
RX packets 1551 bytes 79846 (77.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1642 bytes 8892494 (8.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.96 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::b5f:e696:2650:f930 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:5a:19:a5 txqueuelen 1000 (Ethernet)
RX packets 14084 bytes 9850194 (9.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5620 bytes 584957 (571.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

container模式

        container模式,使用–net=container:container_id/container_name

        多个容器使用共同的网络,看到的ip是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@docker ~]# docker exec -it c07 /bin/bash
[root@c076b8953e9d /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 66 bytes 5364 (5.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@c076b8953e9d /]# exit
[root@docker ~]# docker run -it --rm --net=container:c076 centos_with_net bash
[root@c076b8953e9d /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 66 bytes 5364 (5.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

none模式

        none模式,使用–net=none指定

        这种模式下,不会配置任何网络

1
2
3
4
5
6
7
8
9
10
[root@docker ~]# docker run -it --rm --net=none centos_with_net bash
[root@069e635bea5f /]# ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

bridge模式

        bridge模式,使用–net=bridge指定

        默认模式,不用指定默认就是这种网络模式。这种模式会为每个容器分配一个独立的 Network Namespace。类似于vmware的nat网络模式。同一个宿主机上的所有容器会在同一 个网段下,相互之间是可以通信的。

10.Docker 网络管理 - 外部访问容器

        首先使用centos镜像新建一个容器,然后在该容器中安装httpd服务,并启动

1
2
3
4
5
6
7
8
9
10
11
12
[root@docker ~]# docker exec -it c076 /bin/bash
[root@c076b8953e9d /]# yum install httpd
[root@c076b8953e9d /]# /usr/sbin/httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[root@c076b8953e9d /]# ps aux |grep httpd
root 92 0.1 0.1 221920 3452 ? Ss 12:57 0:00 /usr/sbin/httpd
apache 93 0.0 0.1 221920 2944 ? S 12:57 0:00 /usr/sbin/httpd
apache 94 0.0 0.1 221920 2944 ? S 12:57 0:00 /usr/sbin/httpd
apache 95 0.0 0.1 221920 2944 ? S 12:57 0:00 /usr/sbin/httpd
apache 96 0.0 0.1 221920 2944 ? S 12:57 0:00 /usr/sbin/httpd
apache 97 0.0 0.1 221920 2944 ? S 12:57 0:00 /usr/sbin/httpd
root 101 0.0 0.0 9032 656 ? S+ 12:57 0:00 grep --color=auto httpd

        再把该容器导成一个新的镜像(centos_httpd)

1
2
[root@docker ~]# docker commit -m "centos_httpd" -a "yanyi" c076 centos_httpd
sha256:12fb12486cfe16f66686b55e6c6365c5ecac3211fd97720f9e6e3350da757ed6

        然后再使用新镜像创建容器,并指定端口映射

        docker run -itd -p 5123:80 centos_httpd bash #-p 可以指定端口映射,本例中将容器的80端口映射为本地的5123端口

1
2
[root@docker ~]# docker run -itd -p 5123:80 centos_httpd bash
bbb931e95f37c4202634afa285fbc70c762c3a2a292b0a7655a08ed807ebee43

        docker exec -it container_id bash

1
[root@docker ~]# docker exec -it bbb9 bash

        启动httpd: httpd -k start

1
2
3
4
5
6
7
8
9
10
[root@bbb931e95f37 /]# httpd -k start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.11. Set the 'ServerName' directive globally to suppress this message
[root@bbb931e95f37 /]# ps aux |grep httpd
root 29 0.0 0.1 221920 3456 ? Ss 13:09 0:00 httpd -k start
apache 30 0.0 0.1 221920 2940 ? S 13:09 0:00 httpd -k start
apache 31 0.0 0.1 221920 2940 ? S 13:09 0:00 httpd -k start
apache 32 0.0 0.1 221920 2940 ? S 13:09 0:00 httpd -k start
apache 33 0.0 0.1 221920 2940 ? S 13:09 0:00 httpd -k start
apache 34 0.0 0.1 221920 2940 ? S 13:09 0:00 httpd -k start
root 36 0.0 0.0 9032 656 ? S+ 13:10 0:00 grep --color=auto httpd

        编辑1.html: vim /var/www/html/1.html 随便写点东西

1
[root@bbb931e95f37 /]# vim /var/www/html/1.html
1
2
[root@bbb931e95f37 /]# curl localhost/1.html
yanyi

        退出该容器:exit

        测试: curl 127.0.0.1:5123/1.html

1
2
3
[root@bbb931e95f37 /]# exit
[root@docker ~]# curl 127.0.0.1:5123/1.html
yanyi

        -p后面也支持IP:port:ip:port 的格式,比如

        -p 127.0.0.1:8080:80

        也可以不写本地的端口,只写ip,这样会随意分配一个端口

        -p 127.0.0.1::80

11.Docker 网络管理 – 容器互联

        下载一个mysql镜像

1
[root@docker ~]# docker pull mysql

        新建一个容器,命名为db

1
2
[root@docker ~]# docker run -it -d -p 13306:3306 --name db mysql bash
53247dfe72258636e13b133ee082645cacd48ab6abc4e14442566250c6cd3c24

        在新建一个web容器,并和db互联

docker run -it -d -p 12308:80 –name web –link db:db centos-httpd bash

        在web上运行env命令可以查看到关于db的环境变量

        因 pull 的 mydql 是 Ubuntu 版本,则重新制作 centos 版本

        centos7 yum 没有 mysql-server ,则创建 centos6 容器

1
2
[root@docker ~]# docker run -itd centos-6-x86 bash
3a40c6cd247c6c7083caf2579935fb497fef6b8ca021097766b2d2585ce0642a

        yum 安装 mysql-server

1
2
[root@docker ~]# docker exec -it 3a4 bash
[root@3a40c6cd247c /]# yum install -y mysql.server

        保存镜像

1
2
3
[root@3a40c6cd247c /]# exit
[root@docker ~]# docker commit -m "centos-6-mysql" -a "yanyi" 3a40 centos6-mysql
sha256:7cf0e61cef00084ad7792b8a336490c8d3a53819cc1fa1c1fc8071c8f2f8f8de

        新建一个容器

1
2
[root@docker ~]# docker run -itd -p 13306:3306 centos6-mysql bash
777952322ff56b7c3ab4126e41a4a83a105c04fd785b7d52916d5b8e4a57c17a

        再新建一个 web 容器,并和 mysql 容器互联。

1
2
[root@docker ~]# docker run -itd -p 18080:80 --name web --link elegant_liskov:db centos_httpd bash
d6ec87f1e233256d11fff15d70ce602c1e9163686f4ef128e90bce3ac31fa816

        在web上运行env命令可以查看到关于db的环境变量

12.Docker 网络管理

配置桥接网络(centos7)

        为了使本地网络中的机器和Docker容器更方便的通信,我们经常会有将Docker容器配置到和主机同一网段的需求。这个需求其实很容易实现,我们只要将Docker容器和宿主机的网卡桥接起来,再给Docker容器配上IP就可以了。

        安装 brctl 命令

1
[root@docker ~]# yum install bridge-utils

        编辑网卡配置文件

1
2
3
[root@docker ~]# cd /etc/sysconfig/network-scripts/
[root@docker network-scripts]# cp ifcfg-ens33 ifcfg-br0
[root@docker network-scripts]# vim ifcfg-ens33

        配置 ifcfg-ens33 #增加BRIDGE=br0,删除IPADDR,NETMASK,GATEWAY,DNS1

10

        配置 ifcfg-br0 #修改DEVICE为br0,Type为Bridge,把eth0的网络设置设置到这里来

1
[root@docker network-scripts]# vim ifcfg-br0

11

        重启相关服务,以及关闭相关服务

1
2
3
4
5
[root@docker network-scripts]# systemctl stop NetworkManager
[root@docker network-scripts]# systemctl disable NetworkManager
Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.nm-dispatcher.service.
1
[root@docker network-scripts]# systemctl restart network

        br0 正常启动,能够正常访问该机器即可,再用下面命令查看有即可:

1
2
3
4
[root@docker network-scripts]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000c295a19a5 yes ens33
docker0 8000.0242c3f92b21 no

        修改docker配置文件,修改桥接的网卡以及IP分配范围

1
[root@docker network-scripts]# vim /etc/sysconfig/docker

        将:OPTIONS=’–selinux-enabled’

12

        修改为:OPTIONS=’–selinux-enabled -b=br0 –fixed-cidr=192.168.0.198/26’

13

        重新启动docker

1
2
[root@docker network-scripts]# systemctl stop docker.service
[root@docker network-scripts]# systemctl start docker.service

        新建 docker 容器

1
2
[root@docker ~]# docker run -itd centos7 bash
6cb69dbd31dd3845fc0467c436942d3cf3c08b035b24d26f43433e7c761e0043

        进入容器,查看 IP

1
2
3
4
5
6
7
8
9
10
[root@docker ~]# docker exec -it 6cb6 bash
[root@6cb69dbd31dd /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.192 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::42:c0ff:fea8:c0 prefixlen 64 scopeid 0x20<link>
ether 02:42:c0:a8:00:c0 txqueuelen 0 (Ethernet)
RX packets 1880 bytes 8921311 (8.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1671 bytes 116955 (114.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Docker 网络管理 – 配置桥接网络(centos6)

1
2
[root@docker ~]# cd /etc/sysconfig/network-scripts/
[root@docker network-scripts]# cp ifcfg-eth0 ifcfg-br0

        配置 ifcfg-eth0 #增加BRIDGE=br0,删除IPADDR,NETMASK,GATEWAY,DNS1

1
[root@docker network-scripts]# vim ifcfg-eth0

14

        配置 ifcfg-br0 #修改DEVICE为br0,Type为Bridge,把eth0的网络设置设置到这里来

1
[root@docker network-scripts]# vim ifcfg-br0

15

1
[root@docker network-scripts]# service network restat

        安装 git

1
[root@docker ~]# yum install -y git

        安装pipwork: git clone https://github.com/jpetazzo/pipework;

1
2
3
4
5
6
[root@docker ~]# git clone https://github.com/jpetazzo/pipework
Initialized empty Git repository in /root/pipework/.git/
remote: Counting objects: 489, done.
remote: Total 489 (delta 0), reused 0 (delta 0), pack-reused 489
Receiving objects: 100% (489/489), 167.74 KiB | 28 KiB/s, done.
Resolving deltas: 100% (258/258), done.
1
[root@docker ~]# cp ~/pipework/pipework /usr/local/bin/

        开启一个容器: docker run -itd –net=none –name yanyi centos6-httpd bash

1
2
[root@docker ~]# docker run -itd --net=none --name yanyi centos6-httpd bash
e558b8afb9fc781334fdec93b7b23103bde8bda2a46d2ed14f5b6668d9b99e05

        rpm -Uvh https://repos.fedorapeople.org/openstack/EOL/openstack-grizzly/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm #不安会报错Object “netns” is unknown, try “ip help”

1
2
3
4
5
[root@docker ~]# rpm -Uvh https://repos.fedorapeople.org/openstack/EOL/openstack-grizzly/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
Retrieving https://repos.fedorapeople.org/openstack/EOL/openstack-grizzly/epel-6/iproute-2.6.32-130.el6ost.netns.2.x86_64.rpm
warning: /var/tmp/rpm-tmp.fja3UU: Header V4 RSA/SHA1 Signature, key ID d97b3247: NOKEY
Preparing... ########################################### [100%]
1:iproute ########################################### [100%]

        给容器配置一个 IP :pipework br0 yanyi 192.168.0.199/24@192.168.0.1

1
[root@docker ~]# pipework br0 yanyi 192.168.0.199/24@192.168.0.1

        进入容器

1
[root@docker ~]# docker exec -it yanyi bash

        进去后ifconfig查看就可以看到新添加的ip

16

13. dockerfile 格式

Dockerfile创建镜像 – Dockerfile格式

  • FROM #指定基于哪个基础镜像

        格式 FROM 或者 FROM :, 比如

1
2
FROM centos
FROM centos:latest
  • MAINTAINER #指定作者信息

        格式 MAINTAIN ,比如

1
MAINTAINER yanyi hcldir@qq.com
  • RUN #镜像操作指令

        格式为 RUN 或者 RUN [“executable”, “param1”, “param2”],比如

1
2
RUN yum install httpd
RUN ["/bin/bash", "-c", "echo hello"]
  • CMD # 三种格式:
    • CMD [“executable”, “param1”, “param2”]
    • CMD command param1 param2
    • CMD [“param1”, “param2”]

        RUN和CMD看起来挺像,但是CMD用来指定容器启动时用到的命令,只能有一条。比如

1
CMD ["/bin/bash", "/usr/local/nginx/sbin/nginx", "-c", "/usr/local/nginx/conf/nginx.conf"]
  • EXPOSE

        格式为 EXPOSE […] , 比如

1
EXPOSE 22 80 8443

        这个用来指定要映射出去的端口,比如容器内部我们启动了sshd和nginx,所以我们需要把22和80端口暴漏出去。这个需要配合-P(大写)来工作,也就是说在启动容器时,需要加上-P,让它自动分配。如果想指定具体的端口,也可以使用-p(小写)来指定。

  • ENV

        格式 ENV , 比如

1
ENV PATH /usr/local/mysql/bin:$PATH

        它主要是为后续的RUN指令提供一个环境变量,我们也可以定义一些自定义的变量

        ENV MYSQL_version 5.6

  • ADD 格式 add

        将本地的一个文件或目录拷贝到容器的某个目录里。 其中src为Dockerfile所在目录的相对路径,它也可以是一个url。比如

1
ADD <conf/vhosts> </usr/local/nginx/conf>
  • COPY

        格式同add

        使用方法和add一样,不同的是,它不支持url

  • ENTRYPOINT 格式类似CMD

        容器启动时要执行的命令,它和CMD很像,也是只有一条生效,如果写多个只有最后一条有效。和CMD不同是:

        CMD 是可以被 docker run 指令覆盖的,而ENTRYPOINT不能覆盖。比如,容器名字为yanyi

        我们在Dockerfile中指定如下CMD:

1
CMD [“/bin/echo”, “test ”]

        启动容器的命令是 docker run yanyi 这样会输出 test

        假如启动容器的命令是 docker run -it yanyi /bin/bash 什么都不会输出

        ENTRYPOINT不会被覆盖,而且会比CMD或者docker run指定的命令要靠前执行

        ENTRYPOINT [“echo”, “test”]

        docker run -it yanyi 123

        则会输入 test 123 ,这相当于要执行命令 echo test 123

  • VOLUME

        格式 VOLUME [“/data”]

        创建一个可以从本地主机或其他容器挂载的挂载点。

  • USER

        格式 USER daemon

        指定运行容器的用户

  • WORKDIR

        格式 WORKDIR /path/to/workdir

        为后续的RUN、CMD或者ENTRYPOINT指定工作目录

14. dockerfile 示例-安装 nginx

Dockerfile创建镜像 – Dockerfile示例

        先下载nginx的配置文件 wget http://www.apelearn.com/study_v2/.nginx_conf

1
[root@docker ~]# wget http://www.apelearn.com/study_v2/.nginx_conf

        创建 Dockerfile

1
[root@docker ~]# vim Dockerfile

        内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
############################################################
# Dockerfile to build Nginx Installed Containers
# Based on CentOS
############################################################
# Set the base image to CentOS
FROM centos6
# File Author / Maintainer
MAINTAINER yanyi hcldir@qq.com
# Install necessary tools
RUN yum install -y pcre-devel wget net-tools gcc
RUN yum install -y zlib zlib-devel make
RUN yum install -y openssl-devel
# Install Nginx
ADD http://nginx.org/download/nginx-1.8.0.tar.gz .
RUN tar zxvf nginx-1.8.0.tar.gz
RUN mkdir -p /usr/local/nginx
RUN cd nginx-1.8.0 && ./configure --prefix=/usr/local/nginx && make && make install
RUN rm -fv /usr/local/nginx/conf/nginx.conf
COPY .nginx_conf /usr/local/nginx/conf/nginx.conf
# Expose ports
EXPOSE 80
# Set the default command to execute
# when creating a new container
ENTRYPOINT /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

17

        创建镜像:docker build -t centos_nginx .

1
[root@docker ~]# docker build -t centos-nginx .

        docker images 可以看到我们新建的镜像

1
[root@docker ~]# docker images